/*
 * Copyright 2012 Gene Chen
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package ubc.cs.cpsc210.sustainabilityapp;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import ubc.cs.cpsc210.sustainabilityapp.model.PointOfInterest;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.location.Location;
import android.util.AttributeSet;
import android.view.View;

public class ARView extends View {

	private static final int DARK_BLUE = Color.rgb(0x57, 0x81, 0xFC);
	private static final int RADAR_DIP = 120;

	private double bearing;
	private Location location;
	private List<PointOfInterest> nearbyPOIs = new ArrayList<PointOfInterest>();
	private Paint p;
	private Paint txtP;
	private Bitmap radarCircle;
	private int radarSize;
	private float radarDist;

	PointOfInterest nearest;

	public ARView(Context context, AttributeSet attrs) {
		super(context, attrs);

		radarSize = getPixelsFromDIP(RADAR_DIP);
		radarDist = radarSize/2;
		radarCircle = Bitmap.createBitmap(radarSize, radarSize, Bitmap.Config.ARGB_8888);
		Canvas c = new Canvas(radarCircle);

		txtP = new Paint();
		txtP.setStyle(Paint.Style.FILL);
		txtP.setAntiAlias(true);
		txtP.setTextSize(20);

		p = new Paint();
		p.setStyle(Paint.Style.FILL_AND_STROKE);
		p.setColor(DARK_BLUE);
		p.setStrokeWidth(2);
		p.setAlpha(90);

		c.translate(radarSize/2, radarSize/2);
		// Draw the radar circle
		c.drawCircle(0, 0, radarDist, p);

		// Set the style to stroke so we don't fill the other stuff
		p.setStyle(Paint.Style.STROKE);

		// Draw the next two inner circles
		c.drawCircle(0, 0, radarDist * 2/3, p);
		//noinspection PointlessArithmeticExpression
		c.drawCircle(0, 0, radarDist * 1/3, p);

		// Draw the cross in the middle
		c.drawLine(-radarSize/2, 0, radarSize/2, 0, p);
		c.drawLine(0, -radarSize/2, 0, radarSize/2, p);

		// Draw the visible quadrant lines
		c.drawLine(0, 0,
				(float)(radarDist * Math.cos(5*Math.PI/4)),
				(float)(radarDist * Math.sin(5*Math.PI/4)), p);
		c.drawLine(0, 0,
				(float)(-radarDist * Math.cos(5*Math.PI/4)),
				(float)(radarDist * Math.sin(5*Math.PI/4)), p);

		p.setStyle(Paint.Style.FILL_AND_STROKE);
		p.setStrokeWidth(4);
		p.setAlpha(100);
	}

	private int getPixelsFromDIP(int dip) {
		return (int)(dip * getResources().getDisplayMetrics().density);
	}

	public void orientationChanged(float f) {		
		bearing = Math.toRadians(f);
		this.invalidate();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		drawRadar(canvas);
		drawNearest(canvas);
	}

	private void drawNearest(Canvas canvas) {
		if(nearest == null)
			return;

		int xlat = getPixelsFromDIP(RADAR_DIP+20);
		canvas.translate(getPixelsFromDIP(5), xlat);
		
		float dist = location.distanceTo(nearest.getLocation());
		String text = nearest.getDisplayName() + " (" + new DecimalFormat("#").format(dist) + "m)";
		
		Rect bounds = new Rect();
		txtP.getTextBounds(text, 0, text.length(), bounds);
		
		if((getPixelsFromDIP(5) + bounds.width()) >= radarSize)
			text = nearest.getAbbreviation() + " (" + new DecimalFormat("#").format(dist) + "m)";
		
		canvas.drawText(text, 0, 0, txtP);
	}

	private void drawRadar(Canvas canvas) {
		canvas.drawBitmap(radarCircle, 0, 0, null);
		nearest = null;
		double minDist = 1e99;

		for (PointOfInterest poi: nearbyPOIs) {
			double theta = GeoUtils.bearingRad(location, poi.getLocation()) - bearing;
			double r = GeoUtils.distance(location, poi.getLocation());

			while(theta < 0)
				theta += 2*Math.PI;

			if(r < minDist &&
					theta >= 13*Math.PI/9 &&
					theta <= 14*Math.PI/9) {

				minDist = r;
				nearest = poi;
			}

			if(theta >= 13*Math.PI/9 && theta <= 14*Math.PI/9) 
				p.setColor(0xFF00E000);
			else if(theta >= 5*Math.PI/4 && theta <= 7*Math.PI/4)
				p.setColor(Color.GREEN);
			else
				p.setColor(Color.RED);

			canvas.drawCircle(
					(float)(radarDist + radarDist/1000 * r * Math.cos(theta)),
					(float)(radarDist + radarDist/1000 * r * Math.sin(theta)),
					radarDist/25, p);
		}
	}

	public void updateTour(Location location, List<PointOfInterest> selectedPOIs) {
		this.location = location;
		nearbyPOIs.clear();

		for (PointOfInterest poi: selectedPOIs) {
			Location loc = poi.getLocation();
			Location poiLocation = new Location("");
			poiLocation.setLatitude(loc.getLatitude());
			poiLocation.setLongitude(loc.getLongitude());
			double distValue = location.distanceTo(poiLocation);

			if (distValue <= 1000) {
				nearbyPOIs.add(poi);
			}
		}

		this.invalidate();
	}
}
